package com.whiteape.book.core.page;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.text.TextPaint;

import androidx.core.content.ContextCompat;

import com.gyf.immersionbar.ImmersionBar;
import com.hwangjr.rxbus.RxBus;
import com.hwangjr.rxbus.annotation.Subscribe;
import com.hwangjr.rxbus.annotation.Tag;
import com.hwangjr.rxbus.thread.EventThread;
import com.whiteape.book.R;
import com.whiteape.book.common.RxEvent;
import com.whiteape.book.common.WaConstants;
import com.whiteape.book.core.manager.MediaStorageManager;
import com.whiteape.book.core.manager.ReadSettingManager;
import com.whiteape.book.model.dto.CollectionMediaBean;
import com.whiteape.book.model.dto.DownloadTaskBean;
import com.whiteape.book.model.dto.MediaRecordBean;
import com.whiteape.book.service.VoiceService;
import com.whiteape.book.utils.FileUtils;
import com.whiteape.book.utils.IOUtils;
import com.whiteape.book.utils.ScreenUtils;
import com.whiteape.book.utils.StringUtils;
import com.whiteape.book.utils.ToastUtils;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import io.reactivex.disposables.Disposable;

/**
 * Created by newbiechen on 17-7-1.
 */

public abstract class PageLoader {
    private static final String TAG = "PageLoader";

    // 当前页面的状态
    public static final int STATUS_LOADING = 1;         // 正在加载
    public static final int STATUS_FINISH = 2;          // 加载完成
    public static final int STATUS_ERROR = 3;           // 加载错误 (一般是网络加载情况)
    public static final int STATUS_EMPTY = 4;           // 空数据
    public static final int STATUS_PARING = 5;          // 正在解析 (装载本地数据)
    public static final int STATUS_PARSE_ERROR = 6;     // 本地文件解析错误(暂未被使用)
    public static final int STATUS_CATEGORY_EMPTY = 7;  // 获取到的目录为空
    public static final int STATUS_LAST_CHAPTER = 8;  // 获取到的目录为空
    // 默认的显示参数配置
    private static final int DEFAULT_MARGIN_HEIGHT = 28;
    private static final int DEFAULT_MARGIN_WIDTH = 15;
    private static final int DEFAULT_TIP_SIZE = 12;
    private static final int EXTRA_TITLE_SIZE = 4;

    // 当前章节列表
    protected List<TxtChapter> mChapterList;
    // 书本对象
    protected CollectionMediaBean mCollectionMediaBean;
    // 监听器
    protected OnPageChangeListener mPageChangeListener;

    private Context mContext;
    // 页面显示类
    private PageView mPageView;
    // 当前显示的页
    private TxtPage mCurPage;
    // 上一章的页面列表缓存
    private List<TxtPage> mPrePageList;
    // 当前章节的页面列表
    private List<TxtPage> mCurPageList;
    // 下一章的页面列表缓存
    private List<TxtPage> mNextPageList;

    // 绘制电池的画笔
    private Paint mBatteryPaint;
    // 绘制提示的画笔
    private Paint mTipPaint;
    // 绘制标题的画笔
    private Paint mTitlePaint;
    // 绘制背景颜色的画笔(用来擦除需要重绘的部分)
    private Paint mBgPaint;
    //清除画笔
    private Paint mTransPaint;
    // 绘制小说内容的画笔
    private TextPaint mTextPaint;
    // 阅读器的配置选项
    private ReadSettingManager mSettingManager;
    // 被遮盖的页，或者认为被取消显示的页
    private TxtPage mCancelPage;
    // 存储阅读记录类
    private MediaRecordBean mMediaRecordBean;

    private RectF rectF;
    private Disposable mPreLoadDisp;

    /*****************params**************************/
    // 当前的状态
    protected int mStatus = STATUS_LOADING;
    // 判断章节列表是否加载完成
    protected boolean isChapterListPrepare;

    // 是否打开过章节
    private boolean isChapterOpen;
    private boolean isFirstOpen = true;
    private boolean isClose;
    // 页面的翻页效果模式
    private PageMode mPageMode;
    // 加载器的颜色主题
    private PageStyleNew mPageStyle;
    //当前是否是夜间模式
    private boolean isNightMode;
    //书籍绘制区域的宽高
    private int mVisibleWidth;
    private int mVisibleHeight;
    //应用的宽高
    private int mDisplayWidth;
    private int mDisplayHeight;

    private int mMarginLeft;
    private int mMarginTop;
    private int mMarginRight;
    private int mMarginBottom;

    private int mTipMarginLeft;
    private int mTipMarginTop;
    private int mTipMarginRight;
    private int mTipMarginBottom;

    //间距 改为上下左右四个来控制
//    private int mMarginWidth;
//    private int mMarginHeight;
    //字体的颜色
    private int mTextColor;
    //标题的大小
    private int mTitleSize;
    //字体的大小
    private int mTextSize;
    //行间距
    private int mTextInterval;
    //标题的行间距
    private int mTitleInterval;
    //段落距离(基于行间距的额外距离)
    private int mTextPara;
    //标题距上方的距离
    private int mTitlePara;
    //段首几个字符空格？
    private int mParaStartSpacesNum;
    private String mParaChars;
    //电池的百分比
    private int mBatteryLevel;
    //当前页面的背景
    private String mBgColor;
    private Bitmap mBgBitmap;

    // 当前章
    protected int mCurChapterPos = 0;
    //上一章的记录
    private int mLastChapterPos = 0;

    DecimalFormat decimalFormat = new DecimalFormat("0.00%");

    /**
     * 语音朗读相关
     */
//    private TTSDataListener mTTSDataListener;
    private boolean isTTSRunning;
    //当前听书的第几行
    private int mCurListenParaNum;


    //设置->其它设置相关配置
    private boolean hideStatusBar;
    private boolean hideNavBar;
    private boolean clickToChangePage;
    private boolean volumeToChangePage;
    private boolean showTime;
    private boolean showBattery;
    private boolean showChapterTitle;
    private boolean showPageProgress;
    private boolean showCatalogProgress;

    /*****************************init params*******************************/
    public PageLoader(PageView pageView, CollectionMediaBean collectionMediaBean) {
        RxBus.get().register(this);
        mPageView = pageView;
        mContext = pageView.getContext();
        mCollectionMediaBean = collectionMediaBean;
        mChapterList = new ArrayList<>(1);

        // 初始化数据
        initData();
        // 初始化画笔
        initPaint();
        // 初始化PageView
        initPageView();
        // 初始化书籍
        prepareBook();
    }

    public void setCollectionMediaBean(CollectionMediaBean collectionMediaBean) {
        mCollectionMediaBean = collectionMediaBean;
        mChapterList = new ArrayList<>(1);

        // 初始化数据
        initData();
        // 初始化画笔
        initPaint();
        // 初始化PageView
        initPageView();
        // 初始化书籍
        prepareBook();
    }

    private void initData() {
        // 获取配置管理器
        mSettingManager = ReadSettingManager.getInstance();
        mBgColor = mSettingManager.getPageStyleNew().getBgColor();

        // 获取配置参数
        mPageMode = mSettingManager.getPageMode();
        mPageStyle = mSettingManager.getPageStyleNew();
        // 初始化参数

        mParaStartSpacesNum = mSettingManager.getReadParaStartSpacesNum();
        mTextPara = ScreenUtils.dpToPx(mSettingManager.getReadMargin(ReadSettingManager.READ_MARGIN_TYPE_PARA_INTERVAL));
        mTextInterval = ScreenUtils.dpToPx(mSettingManager.getReadMargin(ReadSettingManager.READ_MARGIN_TYPE_LINE_INTERVAL));
        mMarginLeft = ScreenUtils.dpToPx(mSettingManager.getReadMargin(ReadSettingManager.READ_MARGIN_TYPE_LEFT));
        mMarginTop = ScreenUtils.dpToPx(mSettingManager.getReadMargin(ReadSettingManager.READ_MARGIN_TYPE_TOP));
        mMarginRight = ScreenUtils.dpToPx(mSettingManager.getReadMargin(ReadSettingManager.READ_MARGIN_TYPE_RIGHT));
        mMarginBottom = ScreenUtils.dpToPx(mSettingManager.getReadMargin(ReadSettingManager.READ_MARGIN_TYPE_BOTTOM));

        mTipMarginLeft = ScreenUtils.dpToPx(mSettingManager.getReadMargin(ReadSettingManager.READ_MARGIN_TYPE_TIP_LEFT));
        mTipMarginTop = ScreenUtils.dpToPx(mSettingManager.getReadMargin(ReadSettingManager.READ_MARGIN_TYPE_TIP_TOP));
        mTipMarginRight = ScreenUtils.dpToPx(mSettingManager.getReadMargin(ReadSettingManager.READ_MARGIN_TYPE_TIP_RIGHT));
        mTipMarginBottom = ScreenUtils.dpToPx(mSettingManager.getReadMargin(ReadSettingManager.READ_MARGIN_TYPE_TIP_BOTTOM));


        //other settings
        hideStatusBar = mSettingManager.getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_HIDE_STATUS_BAR);
        hideNavBar = mSettingManager.getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_HIDE_NAV_BAR);
        clickToChangePage = mSettingManager.getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_FULLSCREEN_CLICK_TO_CHANGE_PAGE);
        volumeToChangePage = mSettingManager.getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_VOLUME_TO_CHANGE_PAGE);
        showTime = mSettingManager.getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_SHOW_TIME);
        showBattery = mSettingManager.getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_SHOW_BATTERY);
        showChapterTitle = mSettingManager.getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_SHOW_CHAPTER_TITLE);
        showPageProgress = mSettingManager.getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_SHOW_PAGE_PROGRESS);
        showCatalogProgress = mSettingManager.getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_SHOW_CATALOG_PROGRESS);

//        mMarginWidth = ScreenUtils.dpToPx(DEFAULT_MARGIN_WIDTH);
//        mMarginHeight = ScreenUtils.dpToPx(DEFAULT_MARGIN_HEIGHT);

        // 配置文字有关的参数
        setUpTextParams(mSettingManager.getTextSize());

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < mParaStartSpacesNum; i++) {
            sb.append(" ");
        }
        mParaChars = sb.toString();
    }

    /**
     * @param paraCharNum  段首空格数
     * @param paraInterval 段间距
     * @param lineInterval 行间距
     * @param marginLeft   左边间距
     * @param marginTop    上边间距
     * @param marginRight  右边间距
     * @param marginBottom 下边间距
     */
    public void updateMargin(int paraCharNum, int paraInterval, int lineInterval, int marginLeft,
                             int marginTop, int marginRight, int marginBottom) {
        mParaStartSpacesNum = paraCharNum;
        mTextPara = paraInterval;
        mTextInterval = lineInterval;
        mMarginLeft = marginLeft;
        mMarginTop = marginTop;
        mMarginRight = marginRight;
        mMarginBottom = marginBottom;
        if (mPageMode == PageMode.SCROLL) {
            mPageView.setPageMode(PageMode.SCROLL);
        }

//        mPageView.drawCurPage(false);
        reDrawCurPage(true);

    }

    public void updateMargin() {
        initData();
        updateVisibleWidthAndHeight();
        changeScrollAnimParams();
//        mNextPageList = null;
//        reDrawCurPage(true);
//        preLoadNextChapter();
        openChapter();
    }

    /**
     * @param barChanged 状态栏是否有变化
     */
    public void updateOtherSettings(boolean barChanged) {
        initData();
        if (barChanged) {
            updateVisibleWidthAndHeight();
            changeScrollAnimParams();
        }
//        mNextPageList  = null;
//        reDrawCurPage(true);
//        preLoadNextChapter();
        openChapter();

    }

    /**
     * 作用：设置与文字相关的参数
     *
     * @param textSize
     */
    private void setUpTextParams(int textSize) {
        // 文字大小
        //TODO 行间距和段间距先处理了，剩下的这个title相关的参数日后再说
        mTextSize = textSize;
        mTitleSize = mTextSize + ScreenUtils.spToPx(EXTRA_TITLE_SIZE);
        // 行间距(大小为字体的一半)
//        mTextInterval = mTextSize / 2;
        mTitleInterval = mTitleSize / 2;
        // 段落间距(大小为字体的高度)
//        mTextPara = mTextSize;
        mTitlePara = mTitleSize;
    }

    private void initPaint() {
        // 绘制提示的画笔
        mTipPaint = new Paint();
        mTipPaint.setColor(mTextColor);
        mTipPaint.setTextAlign(Paint.Align.LEFT); // 绘制的起始点
        mTipPaint.setTextSize(ScreenUtils.spToPx(DEFAULT_TIP_SIZE)); // Tip默认的字体大小
        mTipPaint.setAntiAlias(true);
        mTipPaint.setSubpixelText(true);

        // 绘制页面内容的画笔
        mTextPaint = new TextPaint();
        mTextPaint.setColor(mTextColor);
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setAntiAlias(true);
        if (ReadSettingManager.getInstance().getBold()) {
            mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mTextPaint.setStrokeWidth(4);
        }
        // 绘制标题的画笔
        mTitlePaint = new TextPaint();
        mTitlePaint.setColor(mTextColor);
        mTitlePaint.setTextSize(mTitleSize);
        mTitlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mTitlePaint.setTypeface(Typeface.DEFAULT_BOLD);
        mTitlePaint.setAntiAlias(true);

        String typefaceFilePath = mSettingManager.getTypeface();
        if (!StringUtils.isEmpty(typefaceFilePath)) {
            try {
                Typeface typeface = Typeface.createFromFile(typefaceFilePath);
                mTextPaint.setTypeface(typeface);
                mTitlePaint.setTypeface(typeface);
                mTipPaint.setTypeface(typeface);
            } catch (Exception e) {
                mTextPaint.setTypeface(Typeface.DEFAULT);
                mTitlePaint.setTypeface(Typeface.DEFAULT);
                e.printStackTrace();
            }
        }

        // 绘制背景的画笔
        mBgPaint = new Paint();
        mTransPaint = new Paint();
//        mTransPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        mTransPaint.setAlpha(0x40);

//        mBgPaint.setColor(mBgColor);

        // 绘制电池的画笔
        mBatteryPaint = new Paint();
        mBatteryPaint.setAntiAlias(true);
        mBatteryPaint.setDither(true);

        // 初始化页面样式
        setNightMode(mSettingManager.isNightMode());
    }

    private void initPageView() {
        //配置参数
        mPageView.setBgColor(mBgColor);

        mPageView.setPageMode(mPageMode);
    }

    /****************************** public method***************************/

    public boolean isTTSRunning() {
        return isTTSRunning;
    }

    public void startTTS() {
        isTTSRunning = true;
        mCurListenParaNum = 0;
        reDrawCurPage(false);
    }

    public void stopTTS() {
        isTTSRunning = false;
        mCurListenParaNum = 0;
        reDrawCurPage(false);
    }

    /**
     * 跳转到上一章
     *
     * @return
     */
    public boolean skipPreChapter() {
        if (!hasPrevChapter()) {
            return false;
        }

        // 载入上一章。
        if (parsePrevChapter()) {
            mCurPage = getCurPage(0);
        } else {
            mCurPage = new TxtPage();
        }
        mPageView.drawCurPage(false);
        return true;
    }

    /**
     * 跳转到下一章
     *
     * @return
     */
    public boolean skipNextChapter() {
        if (!hasNextChapter()) {
            return false;
        }

        //判断是否达到章节的终止点
        if (parseNextChapter()) {
            mCurPage = getCurPage(0);
        } else {
            mCurPage = new TxtPage();
        }
        mPageView.drawCurPage(false);
        return true;
    }

    /**
     * 跳转到指定章节
     *
     * @param pos:从 0 开始。
     */
    public void skipToChapter(int pos) {
        // 设置参数
        mCurChapterPos = pos;

        // 将上一章的缓存设置为null
        mPrePageList = null;
        // 如果当前下一章缓存正在执行，则取消
        if (mPreLoadDisp != null) {
            mPreLoadDisp.dispose();
        }
        // 将下一章缓存设置为null
        mNextPageList = null;

        // 打开指定章节
        openChapter();
    }

    /**
     * 跳转到指定的页
     *
     * @param pos
     */
    public boolean skipToPage(int pos) {
        if (!isChapterListPrepare) {
            return false;
        }
        mCurPage = getCurPage(pos);
        mPageView.drawCurPage(false);
        return true;
    }

    /**
     * 翻到上一页
     *
     * @return
     */
    public boolean skipToPrePage() {
        return mPageView.autoPrevPage();
    }

    /**
     * 翻到下一页
     *
     * @return
     */
    public boolean skipToNextPage() {
        return mPageView.autoNextPage();
    }

    /**
     * 更新时间
     */
    public void updateTime() {
        if (!mPageView.isRunning()) {
            mPageView.drawCurPage(true);
        }
    }

    /**
     * 更新电量
     *
     * @param level
     */
    public void updateBattery(int level) {
        mBatteryLevel = level;

        if (!mPageView.isRunning()) {
            mPageView.drawCurPage(true);
        }
    }

    /**
     * 设置提示的文字大小
     *
     * @param textSize:单位为 px。
     */
    public void setTipTextSize(int textSize) {
        mTipPaint.setTextSize(textSize);

        // 如果屏幕大小加载完成
        mPageView.drawCurPage(false);
    }

    public void setTypeface(Typeface typeface) {
        mTextPaint.setTypeface(typeface);
        reDrawCurPage(true);
    }

    public void setBold(boolean bold) {
        if (bold) {
            mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mTextPaint.setStrokeWidth(4);
            reDrawCurPage(true);
        } else {
            mTextPaint.setStyle(Paint.Style.FILL);
            reDrawCurPage(true);
        }
    }

    public void setTypeface(String filePath) {
        try {
            Typeface typeface = Typeface.createFromFile(filePath);
            mTextPaint.setTypeface(typeface);
            mTitlePaint.setTypeface(typeface);
            mTipPaint.setTypeface(typeface);
        } catch (Exception e) {
            mTextPaint.setTypeface(Typeface.DEFAULT);
            mTipPaint.setTypeface(Typeface.DEFAULT);
            mTitlePaint.setTypeface(Typeface.DEFAULT_BOLD);
        }
        mSettingManager.setTypeface(filePath);
        // 如果当前已经显示数据
        reDrawCurPage(true);
//        if (isChapterListPrepare && mStatus == STATUS_FINISH) {
//            // 重新计算当前页面
//            dealLoadPageList(mCurChapterPos);
//
//            // 防止在最后一页，通过修改字体，以至于页面数减少导致崩溃的问题
//            if (mCurPage.position >= mCurPageList.size()) {
//                mCurPage.position = mCurPageList.size() - 1;
//            }
//
//            // 重新获取指定页面
//            mCurPage = mCurPageList.get(mCurPage.position);
//        }
//
//        mPageView.drawCurPage(false);
    }

    /**
     * 设置文字相关参数
     *
     * @param textSize
     */
    public void setTextSize(int textSize) {
        // 设置文字相关参数
        setUpTextParams(textSize);

        // 设置画笔的字体大小
        mTextPaint.setTextSize(mTextSize);
        // 设置标题的字体大小
        mTitlePaint.setTextSize(mTitleSize);
        // 存储文字大小
        mSettingManager.setTextSize(mTextSize);
        // 取消缓存
        mPrePageList = null;
        mNextPageList = null;

        // 如果当前已经显示数据
        if (isChapterListPrepare && mStatus == STATUS_FINISH) {
            // 重新计算当前页面
            dealLoadPageList(mCurChapterPos);

            // 防止在最后一页，通过修改字体，以至于页面数减少导致崩溃的问题
            if (mCurPageList != null && mCurPage.position >= mCurPageList.size()) {
                mCurPage.position = mCurPageList.size() - 1;
            }

            // 重新获取指定页面
            mCurPage = mCurPageList.get(mCurPage.position);
        }

        mPageView.drawCurPage(false);
    }

    //各种设置，都需要在STATUS_FINISH的基础上做
    public void setTextInterval(int mode) {
//        mTextInterval = mTextSize / 2;
        this.mTextInterval = mTextSize / mode;
        this.mTextPara = mTextSize / mode;
        if (mStatus != STATUS_FINISH) {
            return;
        }
        reDrawCurPage(true);
        preLoadNextChapter();
    }

    /**
     * tts完成一段文字之后,判断下面的是继续，还是需要翻页
     */
    public void onTTSDone() {
        mCurListenParaNum++;
        int curPageParaNum = 0;
        for (int i = mCurPage.titleLines; i < mCurPage.lines.size(); ++i) {

            String str = mCurPage.lines.get(i);
            if (str.endsWith("\n")) {
                curPageParaNum++;
            }
        }
        //最后一行是否以\n结尾
        boolean lastLineIsNewPara = mCurPage.lines.get(mCurPage.lines.size() - 1).endsWith("\n");
        curPageParaNum = lastLineIsNewPara ? curPageParaNum : curPageParaNum + 1;
        if (mCurListenParaNum >= curPageParaNum) {
            //需要翻页了
            mCurListenParaNum = 0;
            next();
        } else {
            reDrawCurPage(false);
        }
        //TODO 字后一段文字，没有\n
    }

    /**
     * @param refreshData 是否重新排版
     *                    类似TTS这种，只会改变颜色的，不需要要重新排版
     */
    public void reDrawCurPage(boolean refreshData) {
        if (mPageView != null) {
            if (refreshData) {
                //重新排版
                if (isChapterListPrepare && mStatus == STATUS_FINISH) {
                    // 重新计算当前页面
                    dealLoadPageList(mCurChapterPos);
                    //可能正在请求章节内容，这个时候调节，根本不能有效果
                    if (mCurPageList == null || mStatus == STATUS_LOADING) {
                        return;
                    }

                    // 防止在最后一页，通过修改字体，以至于页面数减少导致崩溃的问题
                    if (mCurPage.position >= mCurPageList.size()) {
                        mCurPage.position = mCurPageList.size() - 1;
                    }

                    // 重新获取指定页面
                    mCurPage = mCurPageList.get(mCurPage.position);
                }
            }
            mPageView.drawCurPage(false);
        }
    }

    /**
     * 设置夜间模式
     *
     * @param nightMode
     */
    public void setNightMode(boolean nightMode) {
        mSettingManager.setNightMode(nightMode);
        isNightMode = nightMode;

        if (isNightMode) {
            mBatteryPaint.setColor(Color.WHITE);
            setPageStyle(PageStyleNew.getNightModePageStyle());
        } else {
            mBatteryPaint.setColor(Color.BLACK);
            setPageStyle(mPageStyle);
        }
    }


    /**
     * 设置页面样式
     *
     * @param pageStyle:页面样式
     */
//    public void setPageStyle(PageStyle pageStyle) {
//        if (pageStyle != PageStyle.NIGHT) {
//            mPageStyle = pageStyle;
//            mSettingManager.setPageStyle(pageStyle);
//        }
//
//        if (isNightMode && pageStyle != PageStyle.NIGHT) {
//            return;
//        }
//
//
//        // 设置当前颜色样式
//        mTextColor = ContextCompat.getColor(mContext, pageStyle.getFontColor());
//        mBgColor = ContextCompat.getColor(mContext, pageStyle.getBgColor());
//
//        mTipPaint.setColor(mTextColor);
//        mTitlePaint.setColor(mTextColor);
//        mTextPaint.setColor(mTextColor);
//
//        mBgPaint.setColor(mBgColor);
//
//        mPageView.drawCurPage(false);
//    }
    public void setPageStyle(PageStyleNew pageStyle) {
        if (!pageStyle.isNight()) {
            if (isNightMode) {
                return;
            }
            mPageStyle = pageStyle;
            mSettingManager.setPageStyleNew(pageStyle);
        }

        // 设置当前颜色样式
        mTextColor = Color.parseColor(pageStyle.getFontColor());

//        mBgColor = Color.parseColor(pageStyle.getBgColor());
        mBgColor = pageStyle.getBgColor();
        mPageView.setBgColor(mBgColor);
        if (!mBgColor.startsWith("#")) {
            mBgBitmap = BitmapFactory.decodeFile(mBgColor);
            mPageView.setBackground(new BitmapDrawable(mContext.getResources(), mBgColor));

        } else {
            mPageView.setBackground(new ColorDrawable(Color.parseColor(mBgColor)));
        }

        mTipPaint.setColor(mTextColor);
        mTitlePaint.setColor(mTextColor);
        mTextPaint.setColor(mTextColor);

//        mBgPaint.setColor(mBgColor);

        mPageView.drawCurPage(false);
    }

    /**
     * 翻页动画
     *
     * @param pageMode:翻页模式
     * @see PageMode
     */
    public void setPageMode(PageMode pageMode) {
        mPageMode = pageMode;

        mPageView.setPageMode(mPageMode);
        mSettingManager.setPageMode(mPageMode);

        // 重新绘制当前页
        mPageView.drawCurPage(false);
    }

    /**
     * 设置内容与屏幕的间距
     *
     * @param marginWidth  :单位为 px
     * @param marginHeight :单位为 px
     */
//    public void setMargin(int marginWidth, int marginHeight) {
//        mMarginWidth = marginWidth;
//        mMarginHeight = marginHeight;
//
//        // 如果是滑动动画，则需要重新创建了
//        if (mPageMode == PageMode.SCROLL) {
//            mPageView.setPageMode(PageMode.SCROLL);
//        }
//
//        mPageView.drawCurPage(false);
//    }

    /**
     * 设置页面切换监听
     *
     * @param listener
     */
    public void setOnPageChangeListener(OnPageChangeListener listener) {
        mPageChangeListener = listener;

        // 如果目录加载完之后才设置监听器，那么会默认回调
        if (isChapterListPrepare) {
            mPageChangeListener.onCategoryFinish(mChapterList);
        }
    }

    /**
     * 获取当前页的状态
     *
     * @return
     */
    public int getPageStatus() {
        return mStatus;
    }

    public void setPageStatus(int status) {
        mStatus = status;
    }

    /**
     * 获取书籍信息
     *
     * @return
     */
    public CollectionMediaBean getShelfBook() {
        return mCollectionMediaBean;
    }

    /**
     * 获取章节目录。
     *
     * @return
     */
    public List<TxtChapter> getChapterCategory() {
        return mChapterList;
    }

    /**
     * 获取当前页的页码
     *
     * @return
     */
    public int getPagePos() {
        return mCurPage != null ? mCurPage.position : 0;
    }

    public PageView getPageView() {
        return mPageView;
    }

    /**
     * 获取当前章节的章节位置
     *
     * @return
     */
    public int getChapterPos() {
        return mCurChapterPos;
    }

    public String getChapterTitle() {
        if (mChapterList != null && mChapterList.size() > mCurChapterPos) {
            return mChapterList.get(mCurChapterPos).title;
        }
        return null;
    }

    /**
     * 获取距离屏幕的高度
     *
     * @return
     */
    public int getMarginHeight() {
//        return mMarginHeight;
        return mMarginTop;
    }

    //滚动模式的上边距
    public int getScrollMarginTop() {
        boolean hideStatusBar = ReadSettingManager.getInstance().getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_HIDE_STATUS_BAR);
        return mMarginTop + mTipMarginTop - (int) mTipPaint.getFontMetrics().top /*- (int)mTextPaint.getFontMetrics().top*/ + (hideStatusBar ? 0 : ImmersionBar.getStatusBarHeight((Activity) mContext));
    }

    //滚动模式的下边距, 下边距不用计算nav height，因为那边在onSizeChanged的时候会计算(statusBar变化不会触发onSizeChanged)
    public int getScrollMarginBottom() {
//        boolean hideStatusBar = ReadSettingManager.getInstance().getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_HIDE_STATUS_BAR);
        return mMarginBottom + mTipMarginBottom - (int) mTipPaint.getFontMetrics().top;
    }

    /**
     * 保存阅读记录
     */
    public void saveRecord() {

        if (mChapterList.isEmpty()) {
            return;
        }

        mMediaRecordBean.setMediaId(mCollectionMediaBean.getId());
        if (mCurChapterPos < 0) {
            mCurChapterPos = 0;
        }
        mMediaRecordBean.setChapter(mCurChapterPos);

        if (mCurPage != null) {
            mMediaRecordBean.setPagePos(mCurPage.position);
        } else {
            mMediaRecordBean.setPagePos(0);
        }

        //存储到数据库
        MediaStorageManager.getInstance()
                .saveMediaRecord(mMediaRecordBean);


        //通知主界面更新
        RxBus.get().post(RxEvent.MEDIA_COLLECTION_REFRESH, mCollectionMediaBean);
    }

    /**
     * 初始化书籍
     */
    public void prepareBook() {
        mMediaRecordBean = MediaStorageManager.getInstance()
                .getMediaRecord(mCollectionMediaBean.getId());

        if (mMediaRecordBean == null) {
            mMediaRecordBean = new MediaRecordBean();
        }

        mCurChapterPos = mMediaRecordBean.getChapter();
        if (mCurChapterPos < 0) {
            mCurChapterPos = 0;
        }
        mLastChapterPos = mCurChapterPos;
    }

    /**
     * 打开指定章节
     */
    public void openChapter() {
        isFirstOpen = false;

        if (!mPageView.isPrepare()) {
            return;
        }

        // 如果章节目录没有准备好
        if (!isChapterListPrepare) {
            mStatus = STATUS_LOADING;
            mPageView.drawCurPage(false);
            return;
        }

        // 如果获取到的章节目录为空
        if (mChapterList.isEmpty()) {
            mStatus = STATUS_CATEGORY_EMPTY;
            mPageView.drawCurPage(false);
            return;
        }

        if (parseCurChapter()) {
            // 如果章节从未打开
            if (!isChapterOpen) {
                int position = mMediaRecordBean.getPagePos();

                // 防止记录页的页号，大于当前最大页号
                if (position >= mCurPageList.size()) {
                    position = mCurPageList.size() - 1;
                }
                mCurPage = getCurPage(position);
                mCancelPage = mCurPage;
                // 切换状态
                isChapterOpen = true;
            } else {
                mCurPage = getCurPage(0);
            }
        } else {
            mCurPage = new TxtPage();
        }

        //打开某个章节，先保存进度

        mPageView.drawCurPage(false);
    }

    public void chapterError() {
        //加载错误
        mStatus = STATUS_ERROR;
        mPageView.drawCurPage(false);
    }

    /**
     * 关闭书本
     */
    public void closeBook() {
        isChapterListPrepare = false;
        isClose = true;

        if (mPreLoadDisp != null) {
            mPreLoadDisp.dispose();
        }

        clearList(mChapterList);
        clearList(mCurPageList);
        clearList(mNextPageList);

        mChapterList = null;
        mCurPageList = null;
        mNextPageList = null;
        mPageView = null;
        mCurPage = null;
        RxBus.get().unregister(this);
    }

    private void clearList(List list) {
        if (list != null) {
            list.clear();
        }
    }

    public boolean isClose() {
        return isClose;
    }

    public boolean isChapterOpen() {
        return isChapterOpen;
    }

    /**
     * 加载页面列表
     *
     * @param chapterPos:章节序号
     * @return
     */
    private List<TxtPage> loadPageList(int chapterPos) throws Exception {
        // 获取章节
        TxtChapter chapter = mChapterList.get(chapterPos);
        // 判断章节是否存在
        if (!hasChapterData(chapter)) {
            return null;
        }
        // 获取章节的文本流
        BufferedReader reader = getChapterReader(chapter);
        List<TxtPage> chapters = loadPages(chapter, reader);

        return chapters;
    }

    /*******************************abstract method***************************************/

    /**
     * 刷新章节列表
     */
    public abstract void refreshChapterList();

    public abstract void refreshChapterListAndJumpToChapter(int position);

    /**
     * 获取章节的文本流
     *
     * @param chapter
     * @return
     */
    protected abstract BufferedReader getChapterReader(TxtChapter chapter) throws Exception;

    /**
     * 章节数据是否存在
     *
     * @return
     */
    protected abstract boolean hasChapterData(TxtChapter chapter);

    /***********************************default method***********************************************/

    void drawPage(Bitmap bitmap, boolean isUpdate) {
        drawBackground(mPageView.getBgBitmap(), isUpdate);
//        drawBackground(mPageView.getNextBitmap(), isUpdate);
        if (!isUpdate) {
            drawContent(bitmap);
        }
        //更新绘制
        mPageView.invalidate();
    }

    private void drawBackground(Bitmap bitmap, boolean isUpdate) {
//        if(true)return;
        Canvas canvas = new Canvas(bitmap);
//        Bitmap bitmapSrc = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.bg);
//        int tipMarginHeight = ScreenUtils.dpToPx(3);
        if (!isUpdate) {
            /****绘制背景****/
            //如果没有背景图，就用背景色
            if (mBgColor.startsWith("#")) {
                canvas.drawColor(Color.parseColor(mBgColor));
            } else {
                if (mBgBitmap == null || mBgBitmap.isRecycled()) {
                    mBgBitmap = BitmapFactory.decodeFile(mBgColor);
                }
                //如果mBgBitmap为空，可能是关闭了存储权限或者删除原始图片了
                if (mBgBitmap == null) {
                    ToastUtils.show("背景图丢失，使用默认背景色");
                    mBgColor = "#CEC29C";
                    canvas.drawColor(Color.parseColor(mBgColor));
                } else {
                    canvas.drawBitmap(mBgBitmap, null, rectF, mBgPaint);
                }
            }

            //滚动形式的不需要每次都加上左上标题
            if (showChapterTitle && !mChapterList.isEmpty()) {
                /*****初始化标题的参数********/
                //需要注意的是:绘制text的y的起始点是text的基准线的位置，而不是从text的头部的位置
                float tipTop = mTipMarginTop - mTipPaint.getFontMetrics().top;
                //TODO 直接加上状态栏高度了
                if (!ReadSettingManager.getInstance().getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_HIDE_STATUS_BAR)) {
                    tipTop += ImmersionBar.getStatusBarHeight((Activity) mContext);
                }
                //根据状态不一样，数据不一样
                if (mStatus != STATUS_FINISH) {
                    if (isChapterListPrepare) {
                        if (mCurChapterPos < 0) {
                            mCurChapterPos = 0;
                        }
                        canvas.drawText(mChapterList.get(mCurChapterPos).getTitle()
                                , mMarginLeft, tipTop, mTipPaint);
                    }
                } else {
                    canvas.drawText(mCurPage.title, mTipMarginLeft, tipTop, mTipPaint);
                }

            }
            /******绘制页码********/
            // 底部的字显示的位置Y
            float pagePercentMeasureSize = 0.0f;
            if (showPageProgress) {
                float y = mDisplayHeight - mTipPaint.getFontMetrics().bottom - mTipMarginBottom;
                // 只有finish的时候采用页码
                if (mStatus == STATUS_FINISH) {
                    String percent = (mCurPage.position + 1) + "/" + mCurPageList.size();
//                        canvas.drawText(percent, mMarginWidth, y, mTipPaint);
                    pagePercentMeasureSize = mTipPaint.measureText(percent);
                    canvas.drawText(percent, mTipMarginLeft, y, mTipPaint);
                }
            }
            //总进度
            if(showCatalogProgress){
                float y = mDisplayHeight - mTipPaint.getFontMetrics().bottom - mTipMarginBottom;
                if (mStatus == STATUS_FINISH){
                    float x = mTipMarginLeft;
                    if(showPageProgress){
                        x += pagePercentMeasureSize + ScreenUtils.dpToPx(15);
                    }
                    String catalogProgress = decimalFormat.format(((mCurChapterPos + 1)*1.0f)/mChapterList.size());
                    canvas.drawText(catalogProgress, x, y, mTipPaint);
                }
            }
        } else {
            //擦除区域
            //将图片拉伸之后的部分填充 比如图片是200*300  屏幕是600*900
            //先计算宽和高的拉伸程度,然后再截取原图的部分用于绘制

            //如果只有背景色，用背景色来清除部分区域
            if (mPageMode == PageMode.SCROLL) {
                //滚动的时候，不在画布上画背景图，直接作为画在pageview的背景里面就行
                //滚动的时候，canvas上用透明色作为底色
//                canvas.drawRect(mDisplayWidth / 2, mDisplayHeight - mMarginHeight + ScreenUtils.dpToPx(2), mDisplayWidth, mDisplayHeight, mTransPaint);
            } else {
                if (mBgColor.startsWith("#")) {
                    mBgPaint.setColor(Color.parseColor(mBgColor));
//                    canvas.drawRect(mDisplayWidth / 2, mDisplayHeight - mMarginHeight + ScreenUtils.dpToPx(2), mDisplayWidth, mDisplayHeight, mBgPaint);
                    //TODO 如果配置了tip margin 这里应该是mDisplayHeight - mMarginBottom - mTipMarginBottom
                    canvas.drawRect(mDisplayWidth / 2, mDisplayHeight - mTipMarginBottom - mTipPaint.getTextSize(), mDisplayWidth, mDisplayHeight, mBgPaint);
                } else {
                    // 如果有背景图，用背景图来清除部分区域
                    //TODO 擦除有点问题
                    float scaleY = (mBgBitmap.getHeight() * 1.0f) / mDisplayHeight;
                    Rect rect = new Rect(mBgBitmap.getWidth() / 2, (int) (scaleY * (mDisplayHeight - mTipMarginBottom - mTipPaint.getTextSize())), mBgBitmap.getWidth(), mBgBitmap.getHeight());
//                    RectF rectF = new RectF(mDisplayWidth / 2, mDisplayHeight - mMarginHeight + ScreenUtils.dpToPx(2), mDisplayWidth, mDisplayHeight);
                    RectF rectF = new RectF(mDisplayWidth / 2, mDisplayHeight - mTipMarginBottom - mTipPaint.getTextSize(), mDisplayWidth, mDisplayHeight);
                    canvas.drawBitmap(mBgBitmap, rect, rectF, mBgPaint);
                }
            }

        }

        /******绘制电池********/

//        int visibleRight = mDisplayWidth - mMarginWidth;
//        mMarginWidth = ScreenUtils.dpToPx(DEFAULT_MARGIN_WIDTH);
        int outFrameWidth = (int) mTipPaint.measureText("xxx");
        int visibleRight = mDisplayWidth - mTipMarginRight;
        int visibleBottom = mDisplayHeight - mTipMarginBottom;
        int polarWidth = ScreenUtils.dpToPx(2);
        int polarLeft = visibleRight - polarWidth;
        if (showBattery) {
            int outFrameHeight = (int) mTipPaint.getTextSize();
            int polarHeight = ScreenUtils.dpToPx(6);
            int border = 1;
            int innerMargin = 1;

            //电极的制作
            int polarTop = visibleBottom - (outFrameHeight + polarHeight) / 2;
            Rect polar = new Rect(polarLeft, polarTop, visibleRight,
                    polarTop + polarHeight - ScreenUtils.dpToPx(2));

            mBatteryPaint.setStyle(Paint.Style.FILL);
            canvas.drawRect(polar, mBatteryPaint);

            //外框的制作
            int outFrameLeft = polarLeft - outFrameWidth;
            int outFrameTop = visibleBottom - outFrameHeight;
            int outFrameBottom = visibleBottom - ScreenUtils.dpToPx(2);
            Rect outFrame = new Rect(outFrameLeft, outFrameTop, polarLeft, outFrameBottom);

            mBatteryPaint.setStyle(Paint.Style.STROKE);
            mBatteryPaint.setStrokeWidth(border);
            canvas.drawRect(outFrame, mBatteryPaint);

            //内框的制作
            float innerWidth = (outFrame.width() - innerMargin * 2 - border) * (mBatteryLevel / 100.0f);
            RectF innerFrame = new RectF(outFrameLeft + border + innerMargin, outFrameTop + border + innerMargin,
                    outFrameLeft + border + innerMargin + innerWidth, outFrameBottom - border - innerMargin);

            mBatteryPaint.setStyle(Paint.Style.FILL);
            canvas.drawRect(innerFrame, mBatteryPaint);
        }

        if (showTime) {
            /******绘制当前时间********/
            //底部的字显示的位置Y
            int outFrameLeft = polarLeft - outFrameWidth;
            float y = mDisplayHeight - mTipPaint.getFontMetrics().bottom - mTipMarginBottom;
            String time = StringUtils.dateConvert(System.currentTimeMillis(), WaConstants.FORMAT_TIME);
            float x = (showBattery ? outFrameLeft : visibleRight) - mTipPaint.measureText(time) - ScreenUtils.dpToPx(15);
            canvas.drawText(time, x, y, mTipPaint);
        }
    }

    private void drawContent(Bitmap bitmap) {
//        if(true)return;
        Canvas canvas = new Canvas(bitmap);

//        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC);
        //下面这个清除颜色，最关键是传过来的bitmap这里要是ARGB_8888的，这样才能支持alpha啊
        if (mPageMode == PageMode.SCROLL) {
            canvas.drawColor(0, PorterDuff.Mode.CLEAR);
        }


//        if (mPageMode == PageMode.SCROLL) {
//            bitmap.eraseColor(Color.TRANSPARENT);
//        }
        /******绘制内容****/

        if (mStatus != STATUS_FINISH) {
            //绘制字体
            String tip = "";
            switch (mStatus) {
                case STATUS_LOADING:
                    tip = "正在拼命加载中...";
                    break;
                case STATUS_ERROR:
                    tip = "加载失败(点击边缘重试)";
                    break;
                case STATUS_EMPTY:
                    tip = "文章内容为空";
                    break;
                case STATUS_PARING:
                    tip = "正在排版请等待...";
                    break;
                case STATUS_PARSE_ERROR:
                    tip = "文件解析错误";
                    break;
                case STATUS_CATEGORY_EMPTY:
                    tip = "目录列表为空";
                    break;
                case STATUS_LAST_CHAPTER:
                    tip = "没有更多章节了哦";
                    break;
            }

            //将提示语句放到正中间
            Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
            float textHeight = fontMetrics.top - fontMetrics.bottom;
            float textWidth = mTextPaint.measureText(tip);
            float pivotX = (mDisplayWidth - textWidth) / 2;
            float pivotY = (mDisplayHeight - textHeight) / 2;
            canvas.drawText(tip, pivotX, pivotY, mTextPaint);
        } else {

//            if (mPageMode == PageMode.SCROLL) {
//                top = -mTextPaint.getFontMetrics().top;
//            } else {
            //TODO 如果有tip设置，这里应该是还要算上mTipMarginTop
//                top = mMarginHeight - mTextPaint.getFontMetrics().top;
            float tipTop = mTipMarginTop - mTipPaint.getFontMetrics().top;
            float top = mMarginTop - mTextPaint.getFontMetrics().top + tipTop;
//            }
            if (!ReadSettingManager.getInstance().getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_HIDE_STATUS_BAR)) {
                top += ImmersionBar.getStatusBarHeight((Activity) mContext);
            }
            if (mPageMode == PageMode.SCROLL) {
                //因为scroll模式的bitmap的height已经扣除了该扣除的部分
                //只需要算出开始描绘的起始点在哪（文字的左下角是baseline，需要留出top大的空间）
                top = -mTextPaint.getFontMetrics().top;
            }

            //设置总距离
            int interval = mTextInterval + (int) mTextPaint.getTextSize();
            int para = mTextPara + (int) mTextPaint.getTextSize();
            int titleInterval = mTitleInterval + (int) mTitlePaint.getTextSize();
            int titlePara = mTitlePara + (int) mTextPaint.getTextSize();
            String str = null;

            //对标题进行绘制
            for (int i = 0; i < mCurPage.titleLines; ++i) {
                str = mCurPage.lines.get(i);

                //设置顶部间距
                if (i == 0) {
                    top += mTitlePara;
                }

                //计算文字显示的起始点
//                int start = (int) (mDisplayWidth - mTitlePaint.measureText(str)) / 2;
                int start = 100;
                //进行绘制
                canvas.drawText(str, start, top, mTitlePaint);

                //设置尾部间距
                if (i == mCurPage.titleLines - 1) {
                    top += titlePara;
                } else {
                    //行间距
                    top += titleInterval;
                }
            }

            int paraNum = 0;
            StringBuilder ttsDataSB = new StringBuilder();
            //对内容进行绘制
            for (int i = mCurPage.titleLines; i < mCurPage.lines.size(); ++i) {
                str = mCurPage.lines.get(i);
                //字体变化的过程中，会导致左右margin不一致的情况，字体越大越明显
                //因为字体变大，drawText还是mMarginWidth的左间距，但是后面可能有
                // mMarginWidth + x的间距，其中x < 一个字的大小，也就是恰好装不下
                //一个字的位置。 所以需要把这多出来的x的距离，也减掉才行
                //注意，如果是段落最后一行，不能这么做，因为可能本身不足一行的字体，这样会导致居中显示了
                float marginWidth = (mVisibleWidth - mTextPaint.measureText(str)) / 2.0f;
                marginWidth = (str.endsWith("\n") || marginWidth < 0) ? 0 : marginWidth;

                if (isTTSRunning && paraNum == mCurListenParaNum) {
                    mTextPaint.setColor(ContextCompat.getColor(mContext, R.color.orange));
                    ttsDataSB.append(str);
//                    canvas.drawText(str, mMarginWidth + marginWidth, top, mTextPaint);
                    canvas.drawText(str, mMarginLeft + marginWidth, top, mTextPaint);
                } else {
                    mTextPaint.setColor(mTextColor);
//                    canvas.drawText(str, mMarginWidth + marginWidth, top, mTextPaint);
                    canvas.drawText(str, mMarginLeft + marginWidth, top, mTextPaint);
                }
                if (str.endsWith("\n") || i == mCurPage.lines.size() - 1) {
                    paraNum++;
                }
                if (str.endsWith("\n")) {
                    top += para;
                } else {
                    top += interval;
                }
            }
            //绘制完成，找出需要语音朗读的段落
            String ttsDataStr = ttsDataSB.toString();
            if (isTTSRunning && !StringUtils.isEmpty(ttsDataStr)) {
                //朗读期间，把数据传给VoiceService

                if (mCurChapterPos < 0) {
                    mCurChapterPos = 0;
                }
                String chapterTitle = mChapterList.get(mCurChapterPos).getTitle();
                sendTTSData(chapterTitle, ttsDataStr);
//                        mTTSDataListener.onTtsTextAvailable(ttsDataStr);
            }
        }
    }

    public void setMarginParam() {

    }

    private void sendTTSData(String chapter, String text) {
        if (mContext != null && mCollectionMediaBean != null) {
            VoiceService.play(mContext, mCollectionMediaBean.getTitle(), mCollectionMediaBean.getCoverUrl(),
                    chapter, text);
        }
    }

    private void updateVisibleWidthAndHeight() {
        boolean hideStatusBar = ReadSettingManager.getInstance().getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_HIDE_STATUS_BAR);
        mVisibleWidth = mDisplayWidth - mMarginLeft - mMarginRight;
        mVisibleHeight = mDisplayHeight - mMarginTop - mTipMarginTop + (int) mTipPaint.getFontMetrics().top
                - mMarginBottom - mTipMarginBottom + (int) mTextPaint.getFontMetrics().top - (hideStatusBar ? 0 : ImmersionBar.getStatusBarHeight((Activity) mContext));
    }

    private void changeScrollAnimParams() {
        if (mPageView != null && mPageMode == PageMode.SCROLL) {
            mPageView.setPageMode(PageMode.SCROLL);
        }

    }

    void prepareDisplay(int w, int h) {
        // 获取PageView的宽高
        mDisplayWidth = w;
        mDisplayHeight = h;
        rectF = new RectF(0, 0, mDisplayWidth, mDisplayHeight);

        // 获取内容显示位置的大小
//        mVisibleWidth = mDisplayWidth - mMarginWidth * 2;
        updateVisibleWidthAndHeight();


        // 重置 PageMode
        //变化的时候，下一章节的预加载也需要变化
        mPageView.setPageMode(mPageMode);

        if (!isChapterOpen) {
            // 展示加载界面
            mPageView.drawCurPage(false);
            // 如果在 display 之前调用过 openChapter 肯定是无法打开的。
            // 所以需要通过 display 再重新调用一次。
            if (!isFirstOpen) {
                // 打开书籍
                openChapter();
            }
        } else {
            // 如果章节已显示，那么就重新计算页面
            if (mStatus == STATUS_FINISH) {
                dealLoadPageList(mCurChapterPos);
                // 预加载后面的也得变化
                preLoadNextChapter();
                // 重新设置文章指针的位置
                mCurPage = getCurPage(mCurPage.position);
            }
            mPageView.drawCurPage(false);
        }
    }

    /**
     * 翻阅上一页
     *
     * @return
     */
    boolean prev() {
        // 以下情况禁止翻页
        if (!canTurnPage()) {
            return false;
        }

        if (mStatus == STATUS_FINISH) {
            // 先查看是否存在上一页
            TxtPage prevPage = getPrevPage();
            if (prevPage != null) {
                mCancelPage = mCurPage;
                mCurPage = prevPage;
                mPageView.drawNextPage();
                return true;
            }
        }

        if (!hasPrevChapter()) {
            return false;
        }

        mCancelPage = mCurPage;
        if (parsePrevChapter()) {
            mCurPage = getPrevLastPage();
        } else {
            mCurPage = new TxtPage();
        }
        mPageView.drawNextPage();
        return true;
    }

    /**
     * 解析上一章数据
     *
     * @return:数据是否解析成功
     */
    boolean parsePrevChapter() {
        // 加载上一章数据
        int prevChapter = mCurChapterPos - 1;

        mLastChapterPos = mCurChapterPos;
        mCurChapterPos = prevChapter;

        // 当前章缓存为下一章
        mNextPageList = mCurPageList;

        // 判断是否具有上一章缓存
        if (mPrePageList != null) {
            mCurPageList = mPrePageList;
            mPrePageList = null;

            // 回调
            chapterChangeCallback();
        } else {
            dealLoadPageList(prevChapter);
        }
        return mCurPageList != null && !mCurPageList.isEmpty();
    }

    private boolean hasPrevChapter() {
        //判断是否上一章节为空
        if (mCurChapterPos - 1 < 0) {
            return false;
        }
        return true;
    }

    /**
     * 翻到下一页
     *
     * @return:是否允许翻页
     */
    boolean next() {
        // 以下情况禁止翻页
        if (!canTurnPage()) {
            return false;
        }

        if (mStatus == STATUS_FINISH) {
            // 先查看是否存在下一页
            TxtPage nextPage = getNextPage();
            if (nextPage != null) {
                mCancelPage = mCurPage;
                mCurPage = nextPage;
                mPageView.drawNextPage();
                return true;
            }
        }

        if (!hasNextChapter()) {
//            //最后一张，也用文字表示出来
//            TxtPage nextPage = getNextPage();
//            if (nextPage != null) {
//                mCancelPage = mCurPage;
//                mCurPage = nextPage;
//                mPageView.drawNextPage();
//                return true;
//            }
            return false;
        }

        mCancelPage = mCurPage;
        // 解析下一章数据
        if (parseNextChapter()) {
            mCurPage = mCurPageList.get(0);
        } else {
            mCurPage = new TxtPage();
        }
        mPageView.drawNextPage();
        return true;
    }

    private boolean hasNextChapter() {
        // 判断是否到达目录最后一章
        if (mCurChapterPos + 1 >= mChapterList.size()) {
            return false;
        }
        return true;
    }

    boolean parseCurChapter() {
        // 解析数据
        //如果出现什么意外导致，记录的当前章节号比总得还多了，保险起见设定为0开始
        if (mChapterList.size() <= mCurChapterPos) {
            mCurChapterPos = 0;
        }
        dealLoadPageList(mCurChapterPos);
        // 预加载下一页面
        preLoadNextChapter();
        return mCurPageList != null && !mCurPageList.isEmpty();
    }

    /**
     * 解析下一章数据
     *
     * @return:返回解析成功还是失败
     */
    boolean parseNextChapter() {
        int nextChapter = mCurChapterPos + 1;

        mLastChapterPos = mCurChapterPos;
        mCurChapterPos = nextChapter;

        // 将当前章的页面列表，作为上一章缓存
        mPrePageList = mCurPageList;

        // 是否下一章数据已经预加载了
        if (mNextPageList != null) {
            mCurPageList = mNextPageList;
            mNextPageList = null;
            // 回调
            chapterChangeCallback();
        } else {
            // 处理页面解析
            dealLoadPageList(nextChapter);
        }
        // 预加载下一页面
        preLoadNextChapter();
        return mCurPageList != null && !mCurPageList.isEmpty();
    }

    private void dealLoadPageList(int chapterPos) {
        try {
            mCurPageList = loadPageList(chapterPos);
            if (mCurPageList != null) {
                if (mCurPageList.isEmpty()) {
                    mStatus = STATUS_EMPTY;

                    // 添加一个空数据
                    TxtPage page = new TxtPage();
                    page.lines = new ArrayList<>(1);
                    mCurPageList.add(page);
                } else {
                    mStatus = STATUS_FINISH;
                }
            } else {
                mStatus = STATUS_LOADING;
            }
        } catch (Exception e) {
            e.printStackTrace();

            mCurPageList = null;
            mStatus = STATUS_ERROR;
        }

        // 回调
        chapterChangeCallback();
    }

    private void chapterChangeCallback() {
        if (mPageChangeListener != null) {
            mPageChangeListener.onChapterChange(mCurChapterPos);
            mPageChangeListener.onPageCountChange(mCurPageList != null ? mCurPageList.size() : 0);
        }
    }

    // 预加载下一章
    public void preLoadNextChapter() {
        int nextChapter = mCurChapterPos + 1;

        // 如果不存在下一章，且下一章没有数据，则不进行加载。
        if (!hasNextChapter()
                || !hasChapterData(mChapterList.get(nextChapter))) {
            return;
        }

        //如果之前正在加载则取消
        if (mPreLoadDisp != null) {
            mPreLoadDisp.dispose();
        }

        try {
            //用同步加载，因为后续可能会触发PageView的onSizeChanged，
            //需要这里先执行，那边后执行，如果是异步的话，这里的异步后执行
            //就会导致页面问题
            mNextPageList = loadPageList(nextChapter);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //调用异步进行预加载加载
//        Single.create(new SingleOnSubscribe<List<TxtPage>>() {
//            @Override
//            public void subscribe(SingleEmitter<List<TxtPage>> e) throws Exception {
//                e.onSuccess(loadPageList(nextChapter));
//            }
//        }).compose(RxUtils::toSimpleSingle)
//                .subscribe(new SingleObserver<List<TxtPage>>() {
//                    @Override
//                    public void onSubscribe(Disposable d) {
//                        mPreLoadDisp = d;
//                    }
//
//                    @Override
//                    public void onSuccess(List<TxtPage> pages) {
//                        mNextPageList = pages;
//                    }
//
//                    @Override
//                    public void onError(Throwable e) {
//                        //无视错误
//                    }
//                });
    }

    // 取消翻页
    void pageCancel() {
        if (mCurPage.position == 0 && mCurChapterPos > mLastChapterPos) { // 加载到下一章取消了
            if (mPrePageList != null) {
                cancelNextChapter();
            } else {
                if (parsePrevChapter()) {
                    mCurPage = getPrevLastPage();
                } else {
                    mCurPage = new TxtPage();
                }
            }
        } else if (mCurPageList == null
                || (mCurPage.position == mCurPageList.size() - 1
                && mCurChapterPos < mLastChapterPos)) {  // 加载上一章取消了

            if (mNextPageList != null) {
                cancelPreChapter();
            } else {
                if (parseNextChapter()) {
                    mCurPage = mCurPageList.get(0);
                } else {
                    mCurPage = new TxtPage();
                }
            }
        } else {
            // 假设加载到下一页，又取消了。那么需要重新装载。
            mCurPage = mCancelPage;
        }
    }

    private void cancelNextChapter() {
        int temp = mLastChapterPos;
        mLastChapterPos = mCurChapterPos;
        mCurChapterPos = temp;

        mNextPageList = mCurPageList;
        mCurPageList = mPrePageList;
        mPrePageList = null;

        chapterChangeCallback();

        mCurPage = getPrevLastPage();
        mCancelPage = null;
    }

    private void cancelPreChapter() {
        // 重置位置点
        int temp = mLastChapterPos;
        mLastChapterPos = mCurChapterPos;
        mCurChapterPos = temp;
        // 重置页面列表
        mPrePageList = mCurPageList;
        mCurPageList = mNextPageList;
        mNextPageList = null;

        chapterChangeCallback();

        mCurPage = getCurPage(0);
        mCancelPage = null;
    }

    /**************************************private method********************************************/
    /**
     * 将章节数据，解析成页面列表
     *
     * @param chapter：章节信息
     * @param br：章节的文本流
     * @return
     */
    private List<TxtPage> loadPages(TxtChapter chapter, BufferedReader br) {
        String content = FileUtils.bufferedReaderToString(br);
        //TODO 净化
        content = StringUtils.filterNovelContentByReplaceRule(content, mCollectionMediaBean);
        String[] allLines = content.split("\n");
        int i = 0;
        //生成的页面
        List<TxtPage> pages = new ArrayList<>();
        //使用流的方式加载
        List<String> lines = new ArrayList<>();
        boolean hideStatusBar = ReadSettingManager.getInstance().getReadOtherSettings(ReadSettingManager.READ_OTHER_SETTING_HIDE_STATUS_BAR);

        int rHeight = mVisibleHeight;
        int titleLinesCount = 0;
        boolean showTitle = true; // 是否展示标题
        String paragraph = chapter.getTitle();//默认展示标题
        // TODO 净化
        paragraph = StringUtils.filterNovelContentByReplaceRule(paragraph, mCollectionMediaBean);

        try {
            while (showTitle || i < allLines.length) {
                paragraph = StringUtils.convertCC(paragraph, mContext);
                //段首几个空格，这里的paragraph中可以控制
                // 重置段落
                if (!showTitle) {
                    paragraph = allLines[i].replaceAll("\\s", "").trim();
                    i++;
                    paragraph = paragraph.replaceAll("\\s", "");
                    // 如果只有换行符，那么就不执行
                    if (paragraph.equals("")) continue;
                    paragraph = StringUtils.halfToFull(mParaChars + paragraph + "\n");
                } else {
                    //设置 title 的顶部间距
                    rHeight -= mTitlePara;
                }
                int wordCount = 0;
                String subStr = null;
                while (paragraph.length() > 0) {
                    //当前空间，是否容得下一行文字
                    if (showTitle) {
                        rHeight -= mTitlePaint.getTextSize();
                    } else {
                        rHeight -= mTextPaint.getTextSize();
                    }
                    // 一页已经填充满了，创建 TextPage
                    if (rHeight <= 0) {
                        // 创建Page
                        TxtPage page = new TxtPage();
                        page.position = pages.size();
                        page.title = StringUtils.convertCC(chapter.getTitle(), mContext);
                        page.lines = new ArrayList<>(lines);
                        page.titleLines = titleLinesCount;
                        pages.add(page);
                        // 重置Lines
                        lines.clear();
                        rHeight = mVisibleHeight;// + /*(int) mTipPaint.getFontMetrics().top /*+ (int) mTextPaint.getFontMetrics().top*/ - (hideStatusBar ? 0 : ImmersionBar.getStatusBarHeight((Activity) mContext));
//                        rHeight = mVisibleHeight + (int) mTipPaint.getFontMetrics().top + (int) mTextPaint.getFontMetrics().top - (hideStatusBar ? 0 : ImmersionBar.getStatusBarHeight((Activity) mContext));
                        titleLinesCount = 0;

                        continue;
                    }

                    //测量一行占用的字节数
                    if (showTitle) {
                        wordCount = mTitlePaint.breakText(paragraph,
                                true, mVisibleWidth, null);
                    } else {
                        wordCount = mTextPaint.breakText(paragraph,
                                true, mVisibleWidth, null);
                    }

                    subStr = paragraph.substring(0, wordCount);
                    if (!subStr.equals("\n")) {
                        //将一行字节，存储到lines中
                        lines.add(subStr);

                        //设置段落间距
                        if (showTitle) {
                            titleLinesCount += 1;
                            rHeight -= mTitleInterval;
                        } else {
                            rHeight -= mTextInterval;
                        }
                    }
                    //裁剪
                    paragraph = paragraph.substring(wordCount);
                }

                //增加段落的间距
                if (!showTitle && lines.size() != 0) {
                    rHeight = rHeight - mTextPara + mTextInterval;
                }

                if (showTitle) {
                    rHeight = rHeight - mTitlePara + mTitleInterval;
                    showTitle = false;
                }
            }

            if (lines.size() != 0) {
                //创建Page
                TxtPage page = new TxtPage();
                page.position = pages.size();
                page.title = StringUtils.convertCC(chapter.getTitle(), mContext);
                page.lines = new ArrayList<>(lines);
                page.titleLines = titleLinesCount;
                pages.add(page);
                //重置Lines
                lines.clear();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.close(br);
        }
        return pages;
    }


    /**
     * @return:获取初始显示的页面
     */
    private TxtPage getCurPage(int pos) {
        if (mPageChangeListener != null) {
            mPageChangeListener.onPageChange(pos);
        }
        //TODO BUG
        //如果是最后一页，只有一两句的话，那么点击的时候，因为状态栏的问题，导致当前页面
        //出现的问题
        //或者上下滚动的时候，直接点击中间，也有问题
        if (pos >= mCurPageList.size()) {
            pos = mCurPageList.size() - 1;
        }
        return mCurPageList.get(pos);
    }

    /**
     * @return:获取上一个页面
     */
    private TxtPage getPrevPage() {
        int pos = mCurPage.position - 1;
        if (pos < 0) {
            return null;
        }
        if (mPageChangeListener != null) {
            mPageChangeListener.onPageChange(pos);
        }
        if (pos > mCurPageList.size() - 1) {
            pos = mCurPageList.size() - 1;
        }
        return mCurPageList.get(pos);
    }

    /**
     * @return:获取下一的页面
     */
    private TxtPage getNextPage() {
        int pos = mCurPage.position + 1;
        if (pos >= mCurPageList.size()) {
            return null;
        }
        if (mPageChangeListener != null) {
            mPageChangeListener.onPageChange(pos);
        }
        return mCurPageList.get(pos);
    }

    /**
     * @return:获取上一个章节的最后一页
     */
    private TxtPage getPrevLastPage() {
        int pos = mCurPageList.size() - 1;

        if (mPageChangeListener != null) {
            mPageChangeListener.onPageChange(pos);
        }

        return mCurPageList.get(pos);
    }

    /**
     * 根据当前状态，决定是否能够翻页
     *
     * @return
     */
    private boolean canTurnPage() {

        if (!isChapterListPrepare) {
            return false;
        }

        if (mStatus == STATUS_PARSE_ERROR
                || mStatus == STATUS_PARING) {
            return false;
        } else if (mStatus == STATUS_ERROR) {
            mStatus = STATUS_LOADING;
        }
        return true;
    }

    /*****************************************interface*****************************************/

    public interface OnPageChangeListener {
        /**
         * 作用：章节切换的时候进行回调
         *
         * @param pos:切换章节的序号
         */
        void onChapterChange(int pos);

        /**
         * 作用：请求加载章节内容
         *
         * @param requestChapters:需要下载的章节列表
         */
        void requestChapters(List<TxtChapter> requestChapters);

        /**
         * 作用：章节目录加载完成时候回调
         *
         * @param chapters：返回章节目录
         */
        void onCategoryFinish(List<TxtChapter> chapters);

        /**
         * 作用：章节页码数量改变之后的回调。==> 字体大小的调整，或者是否关闭虚拟按钮功能都会改变页面的数量。
         *
         * @param count:页面的数量
         */
        void onPageCountChange(int count);

        /**
         * 作用：当页面改变的时候回调
         *
         * @param pos:当前的页面的序号
         */
        void onPageChange(int pos);
    }

    public interface TTSDataListener {
        void onTtsTextAvailable(String text);
    }

    @Subscribe(thread = EventThread.IO,
            tags = {@Tag(RxEvent.DOWNLOADED_FILE_DELETED)})
    public void onDownloadTaskStatusChanged(ArrayList<DownloadTaskBean> taskBeanList) {
        for (DownloadTaskBean taskBean : taskBeanList) {
            if (taskBean.getMediaId() != null && taskBean.getMediaId().equals(mCollectionMediaBean.getId())) {
                //删除的包括当前书籍的内容，需要重新加载下一页
                preLoadNextChapter();
            }
        }

    }
}
